package com.juku2024.juku

import android.content.Context
import android.content.Intent
import android.net.Uri
import android.os.Bundle
import android.text.TextUtils
import android.util.Log
import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
import android.widget.TextView
import androidx.constraintlayout.widget.Group
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.blankj.utilcode.util.NetworkUtils
import com.juku2024.juku.adapter.CategoryListAdapter
import com.juku2024.juku.adapter.VideoDetailEpisodeAdapter
import com.juku2024.juku.analysis.AnalysisVideoTools
import com.juku2024.juku.analysis.OnParseVideoListener
import com.juku2024.juku.base.BaseActivity
import com.juku2024.juku.base.BaseApplication
import com.juku2024.juku.callback.OnCastScreenCallback
import com.juku2024.juku.callback.OnEpisodeClickCallback
import com.juku2024.juku.db.entity.VideoEntity
import com.juku2024.juku.db.entity.VideoRecommendModel
import com.juku2024.juku.dialog.VideoCasScreenDialog
import com.juku2024.juku.dialog.VideoDesDialog
import com.juku2024.juku.dialog.VideoEpisodeDialog
import com.juku2024.juku.dialog.VideoSourceDialog
import com.juku2024.juku.model.EpisodesResponse
import com.juku2024.juku.model.PlayInfoResponse
import com.juku2024.juku.network.retrofit.OnRetrofitResultListener
import com.juku2024.juku.tools.AlertUtils
import com.juku2024.juku.tools.AnalysisUtils
import com.juku2024.juku.tools.AppUtils
import com.juku2024.juku.tools.Constants
import com.juku2024.juku.tools.LogC
import com.juku2024.juku.tools.SPUtil
import com.juku2024.juku.tools.WrapGridLayoutManager
import com.juku2024.juku.tools.WrapLinearLayoutManager
import com.juku2024.juku.viewmodel.VideoDetailViewModelNew
import com.juku2024.juku.widget.ControlEpisodeListView
import com.juku2024.juku.widget.LoadingView
import com.juku2024.juku.widget.VideoScreenViewNew
import com.rabbit.videoplayer.MixPlayerView
import com.rabbit.videoplayer.OnChangeEpisodeListener
import com.rabbit.videoplayer.listener.OnAdReadyLoadListener
import com.rabbit.videoplayer.listener.OnCastScreenListener
import com.rabbit.videoplayer.listener.OnFullScreenStatusListener
import com.rabbit.videoplayer.listener.OnLoadUnlockAdListener
import com.rabbit.videoplayer.listener.OnVodCompleteListener
import com.rabbit.videoplayer.listener.OnVodErrorListener
import com.rabbit.videoplayer.listener.player.OnPreparedListener
import com.rabbit.videoplayer.response.PlayerType
import com.wanban.adutils.callback.OnLoadAdCallback
import com.wanban.adutils.tools.AdConstants
import com.wanban.adutils.utils.CommonAdTools
import com.wanban.adutils.utils.VideoInterstitialAdTools
import io.reactivex.Flowable
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.disposables.Disposable
import io.reactivex.schedulers.Schedulers
import java.util.concurrent.TimeUnit


class VideoDetailActivity : BaseActivity(){

    companion object {
        fun toVideoDetail(context: Context, videoId: Long?, videoName: String?, isSkitsVideo: Boolean = false, pic: String? = null) {
            if (BaseApplication.isLimited) {
                val url = "https://baike.baidu.com/item/$videoName"
                val intent = Intent(Intent.ACTION_VIEW)
                intent.setData(Uri.parse(url))
                context.startActivity(intent)
            } else {
                val id = videoId ?: 0L
                val intent = Intent(context, VideoDetailActivity::class.java)
                intent.putExtra(Constants.AROUTER_KEY_VIDEO_ID, id)
                context.startActivity(intent)

//                VideoPlayerSkitsActivity.toPlayerActivity(context, id, videoName, pic)
            }
        }

        fun toPlayerActivity(context: Context, id: Long, name: String?, pic: String?){
            val intent = Intent(context, VideoPlayerSkitsActivity::class.java)
            intent.putExtra(Constants.AROUTER_KEY_VIDEO_ID, id)
            intent.putExtra(Constants.AROUTER_KEY_VIDEO_NAME, name)
            intent.putExtra(Constants.AROUTER_KEY_VIDEO_PICTURE, pic)
            context.startActivity(intent)
        }
    }

    private lateinit var btnShare: View
    private lateinit var btnDownload: View
    private lateinit var btnFavorite: View
    private lateinit var recommendGroup: Group
    private lateinit var ivFavorite: ImageView
    private lateinit var tvVideoDes: TextView
    private lateinit var tvVideoName: TextView
    private lateinit var tvCommonProblem: TextView
    private lateinit var videoUIContainer: View
    private lateinit var btnShowDesDialog: View
    private lateinit var adBannerRoot: ViewGroup
    private lateinit var loadingView: LoadingView
    private lateinit var tvEpisodeCount: TextView
    private lateinit var tvEpisodeOrder: TextView
    private lateinit var tvSourceContent: TextView
    private lateinit var btnShowSourceDialog: View
    private lateinit var btnShowEpisodeDialog: View
    private lateinit var videoPlayer: MixPlayerView
    private lateinit var recommendLoadingView: LoadingView
    private lateinit var episodeRecyclerView: RecyclerView
    private lateinit var recommendRecyclerView: RecyclerView
    private lateinit var fullEpisodeView: ControlEpisodeListView
    private lateinit var videoScreen: VideoScreenViewNew


    // 视频id
    private var videoId: Long = -1
    private var videoUrl: String? = null
    // 是否用户手动点击切换视频源
    private var isManualChangeSource = false
    private var bannerAdTools: CommonAdTools? = null
    private var pauseAdTools: CommonAdTools? = null
    // 显示视频简介dialog
    private var videoDesDialog: VideoDesDialog? = null
    // 显示视频线路dialog
    private var videoSourceDialog: VideoSourceDialog? = null
    // 显示剧集列表dialog
    private var videoEpisodeDialog: VideoEpisodeDialog? = null
    // 显示投屏的dialog
    private var videoCasScreenDialog: VideoCasScreenDialog? = null
    // 出错视频集合，k:出错源id，v:出错剧集数, 例如2 -> 1,3: 表示源id的第2和第四集出错，无法播放
    private val errorSourceEpisodeMap by lazy { HashMap<Int, ArrayList<Int>>() }
    // 相关视频推荐列表
    private val recommendListAdapter by lazy { CategoryListAdapter(ArrayList()) }
    // 横向聚集列表Adapter
    private val episodeListAdapter by lazy { VideoDetailEpisodeAdapter(ArrayList()) }
    // 数据控制器
    private val viewModel by lazy { getViewModel(VideoDetailViewModelNew::class.java) }
    // 当前支持的播放器集合
    private val playerList = arrayListOf(PlayerType.ALIYUN, PlayerType.MEDIA3)
    // 线路统计
    private var sourceDisposable: Disposable? = null

    override fun getLayoutResId(): Int {
        return R.layout.activity_video_detail_new
    }

    override fun initView() {
        super.initView()
        btnShare = findViewById(R.id.btnShare)
        btnDownload = findViewById(R.id.btnDl)
        btnFavorite = findViewById(R.id.btnFavorite)
        ivFavorite = findViewById(R.id.iv_video_favorite)
        tvVideoDes = findViewById(R.id.tv_video_des)
        tvVideoName = findViewById(R.id.tv_video_name)
        tvSourceContent = findViewById(R.id.tvSourceContent)
        tvEpisodeOrder = findViewById(R.id.tvEpisodeOrder)
        tvEpisodeCount = findViewById(R.id.tvEpisodeCount)
        loadingView = findViewById(R.id.video_detail_loadView)
        videoPlayer = findViewById(R.id.videoPlayer)
        episodeRecyclerView = findViewById(R.id.episodeRecyclerView)
        videoUIContainer = findViewById(R.id.scrollVideo)
        recommendGroup = findViewById(R.id.recommendGroup)
        recommendRecyclerView = findViewById(R.id.recyclerRecommend)
        recommendLoadingView = findViewById(R.id.recommendLoadingView)
        btnShowDesDialog = findViewById(R.id.linearDes)
        btnShowSourceDialog = findViewById(R.id.layoutSource)
        btnShowEpisodeDialog = findViewById(R.id.layoutVideoEpisode)
        adBannerRoot = findViewById(R.id.adBannerRoot)
        fullEpisodeView = findViewById(R.id.fullEpisodeView)
        videoScreen = findViewById(R.id.videoScreenNew)
        tvCommonProblem = findViewById(R.id.tv_common_problem)
        // 横向剧集列表
        episodeRecyclerView.layoutManager = WrapLinearLayoutManager(this, RecyclerView.HORIZONTAL)
        episodeRecyclerView.adapter = episodeListAdapter
        // 推荐列表
        recommendRecyclerView.layoutManager = WrapGridLayoutManager(this, 3)
        recommendRecyclerView.adapter = recommendListAdapter
    }


    override fun bindEvent() {
        super.bindEvent()
        // 显示简介
        btnShowDesDialog.setOnClickListener {
            showVideoDesDialog()
        }
        // 显示线路选择
        btnShowSourceDialog.setOnClickListener {
            showVideoSourceDialog()
        }
        // 显示剧集列表
        btnShowEpisodeDialog.setOnClickListener {
            showEpisodeDialog()
        }
        // 点击收藏
        btnFavorite.setOnClickListener {
            // 更新收藏状态
            setFavoriteUI(viewModel.switchFavoriteStatus(videoId))
        }
        // 排序
        tvEpisodeOrder.setOnClickListener {
            switchEpisodeListOrder()
        }
        // 点击下载
        btnDownload.setOnClickListener {
            videoPlayer.pause()
            val intent = Intent(this@VideoDetailActivity, VideoDownloadActivity::class.java)
            intent.putExtra(Constants.AROUTER_KEY_VIDEO_ID, videoId)
            intent.putExtra(Constants.INTENT_KEY_VIDEO_SOURCE_ID, viewModel.currentSourceId)
            startActivity(intent)
        }
        // 分型App
        btnShare.setOnClickListener {
            AppUtils.shareApp(this@VideoDetailActivity)
        }

        tvCommonProblem.setOnClickListener {
            videoPlayer.pause()
            val intent = Intent(this@VideoDetailActivity, CommonProblemActivity::class.java)
            startActivity(intent)
        }

        // 点击相关推荐
        recommendListAdapter.setOnItemClickListener { _, _, position ->
            // 先保存历史记录
            updatePlayHistory()
            stopSourceReport()
            val item = recommendListAdapter.getItem(position)
            toVideoDetail(this, item.id, item.name)
        }

        // 点击剧集列表
        episodeListAdapter.setOnItemClickListener { _, _, position ->
            if (episodeListAdapter.getItem(position).isPlaying) return@setOnItemClickListener
            // 先保存历史记录
            toPlayEpisode(position)
        }

        fullEpisodeView.setEpisodeClickCallback(object : com.rabbit.videoplayer.listener.OnEpisodeClickCallback {
            override fun onEpisodeClick(position: Int, realPos: Int) {
                // 设置是否显示播放下一个
                toPlayEpisode(position)
            }
        })


        // 播放器切换剧集监听
        videoPlayer.setVodChangeEpisodeListener(object : OnChangeEpisodeListener {
            override fun onChangeEpisode(position: Int) {
                // 获取当前正在播放的剧集的position
                toPlayEpisode(position)
            }

            override fun onPlayNext(): Boolean {
                val currentPlayingItemIndex = getCurrentPlayingEpisodeIndex()
                val defaultOrderIndex =  if (viewModel.isEpisodeReverse) {
                    episodeListAdapter.data.size - currentPlayingItemIndex - 1
                } else {
                    currentPlayingItemIndex
                }
                // 已经最后一集了，不再播放下一集
                if (defaultOrderIndex >= episodeListAdapter.data.size - 1) {
                    stopSourceReport()
                    return false
                }
                val targetIndex = if (viewModel.isEpisodeReverse) {
                    currentPlayingItemIndex - 1
                } else {
                    currentPlayingItemIndex + 1
                }
                // 播放视频
                toPlayEpisode(targetIndex)
                return targetIndex < episodeListAdapter.data.size - 1
            }

            override fun showEpisodeList() {
                fullEpisodeView.onEpisodeSelected()
            }

            override fun onPause() {
                LogC.e("Player -> 用户点击了暂停....")
                stopSourceReport()
                updatePlayHistory()
            }
        })

        videoPlayer.setVodPreparedListener(object: OnPreparedListener {
            override fun onPrepared() {
                LogC.e("播放器SDK -> 详情页  onPrepared...")
                val typeStr = when(videoPlayer.getPlayerType()) {
                    PlayerType.ALIYUN -> "阿里"
                    else -> "Media3"
                }
                AnalysisUtils.analysis(Constants.EVENT_PLAYER_TYPE, Constants.KEY_TYPE, typeStr)
                startSourceReport()

                videoPlayer.start()
            }
        })

        videoPlayer.setVodCompleteListener(object : OnVodCompleteListener {
            override fun onVodComplete(): Boolean {
                stopSourceReport()
                // 默认是继续播放下一集
                val episodeList = viewModel.getCurrentSourceData()?.episodes?:return false
                val currentSource = episodeList.size
                val index = episodeList.indexOfFirst { it.isPlaying }
                if (index >= currentSource - 1) { // 播放到最后一集，无法再自动播放了
                    return true
                }
                return false
            }
        })

        // 播放器出错提示
        videoPlayer.setVodErrorListener(object : OnVodErrorListener {
            override fun onRetry() {
                videoPlayer.showLoadingStatus()
                videoPlayer.postDelayed({
                    // 如果已下载的视频，无需在做解析，直接播放
                    val videoName = viewModel.videoDetailModel?.name
                    // 当前线路的剧集列表
                    val episodeList = episodeListAdapter.data as ArrayList
                    val episode = episodeListAdapter.getItem(viewModel.currentEpisodePosition)
                    // 获取播放的真正url，有的线路需要解析
                    parseVideoUrl(videoName, episode, episodeList)
                }, 500)
            }

            override fun onVodError(errorMsg: String?): Boolean {
                stopSourceReport()
                LogC.e("player -> onVodError...")
                if (!NetworkUtils.isConnected()) {
                    return true
                }
                val episodeList = episodeListAdapter.data as ArrayList
                val episode = episodeList.firstOrNull { it.isPlaying }
                if (episode?.isDownloaded == true) { // 下载失败的视频，无需重试，直接提示失败
                    return true
                }

                // 尝试获取可用的播放器
                val playerType = getAvailablePlayer()
                LogC.e("切换播放器 -> 当前可用播放器 -> $playerType")
                if (playerType != -1) {
                    // 切换播放
                    videoPlayer.switchPlayer(playerType)
                    return false
                }
                // 此时播放器已经都尝试了，恢复播放器列表
                resetPlayerTypeList()
                // 切换回默认的第一个播放器
                LogC.e("切换播放器 -> 此时播放器已经都尝试了，开始使用其他方式恢复播放")
                // 如果是解析的源，先处理解析
                // 先移除已经失败的播放源
                AnalysisVideoTools.removeUselessSource()
                return if (AnalysisVideoTools.hasUsefulUrl()) {
                    // 显示加载状态
                    videoPlayer.showLoadingStatus()
                    // 继续等待解析出新的地址
                    val parseItem = AnalysisVideoTools.getCacheParseContent() ?: return false
                    videoUrl = parseItem.url

                    videoPlayer.playVideo(
                        // 播放url
                        parseItem.url!!,
                        episode?.videoTitle,
                        // 跳转进度
                        viewModel.getPlayStartPosition(),
                        viewModel.currentEpisodePosition,
                        episodeList.size,
                        false,
                        parseItem.headerMap,
                        getCurrentPlayerType()
                    )
                    false
                } else {
                    autoChangeAvailabilitySource()
                }
            }
        })


        videoPlayer.setOnLoadUnlockAdListener(object : OnLoadUnlockAdListener {
            override fun onLoadUnlockAd() {
                videoPlayer.hideUnlockUI()
                // 加载广告
                viewModel.loadMultipleAd(this@VideoDetailActivity, VideoDetailViewModelNew.AD_TYPE_UNLOCK) {
                    if (isActivityNotActive()) return@loadMultipleAd
                    // 修改当前剧集的解锁标签
                    viewModel.clearCurrentEpisodeUnlockAdTag()
                    episodeListAdapter.setList(episodeListAdapter.data)

                    // 选出当前要播放的剧集数
                    val episode = viewModel.getCurrentSourceData()?.episodes?.firstOrNull { it.isPlaying }
                    if (episode == null) {
                        showVideoEpisodeFailureDialog()
                        return@loadMultipleAd
                    }
                    playEpisode(episode)
                }
            }
        })


        // 点击投屏
        videoPlayer.setCastScreenListener(object : OnCastScreenListener {

            override fun onCastScreen() {
                videoPlayer.onVodSuspend()
                showCastScreenBrowseDialog()
            }

            override fun onCloseCastScreen() {
                if (videoCasScreenDialog?.isShowing == true) {
                    videoCasScreenDialog?.dismiss()
                }
                videoCasScreenDialog?.disconnect()

                videoPlayer.start()
            }

            override fun onCastScreenPlay(): Boolean {
                return videoCasScreenDialog?.startOrPauseCastScreen() ?: false
            }

            override fun seekTo(seek: Long) {
                videoCasScreenDialog?.castScreenSeekTo(seek.toInt())
            }

            override fun isStartTrackingTouch(isTouchOn: Boolean) {
                videoCasScreenDialog?.isStopUpdateCurrentPosition(isTouchOn)
            }

        })

        videoPlayer.setOnLoadPauseAdListener(object: OnAdReadyLoadListener {
            override fun onReady2LoadAd() {
                loadPauseAd()
            }
        })

        videoPlayer.setFullScreenStatusListener(object: OnFullScreenStatusListener {
            override fun onFullScreen(isFullScreen: Boolean) {
                if (videoCasScreenDialog == null) {
                    videoCasScreenDialog = VideoCasScreenDialog(this@VideoDetailActivity)
                }
                videoCasScreenDialog?.setFullScreenStatus(isFullScreen)

                // 控制是否可以录屏
                isScreenRecord(!isFullScreen)
            }
        })
    }

    override fun init(savedInstanceState: Bundle?) {
        // 获取当前视频id
        videoId = intent?.getLongExtra(Constants.AROUTER_KEY_VIDEO_ID, -1L) ?: -1L
        if (videoId < 0) {
            showVideoFailureDialog()
            return
        }
        // 加载详情接口
        loadVideoDetail()
        // 加载插屏广告
        loadInterstitialAd()
        // 加载原生广告
        loadBannerAd()
    }

    private fun loadVideoDetail() {
        loadingView.showLoading()
        viewModel.getVideoDetail(videoId, object : OnRetrofitResultListener<VideoEntity> {
            override fun onSuccess(t: VideoEntity) {
                // 显示详情页的UI
                showVideoUI(t)
                // 继续加载推荐列表
                loadVideoRecommend()
            }

            override fun onFailed(msg: String) {
                loadingView.showErrorStatus(msg, getString(R.string.retry)) {
                    loadingView.showLoading()
                    loadingView.postDelayed({
                        loadVideoDetail()
                    }, 500)
                }
            }
        })
    }

    private fun loadVideoRecommend() {
        recommendLoadingView.showLoading()
        val genreId = viewModel.videoDetailModel?.type_id ?: 0
        viewModel.getVideoRecommend(genreId, object : OnRetrofitResultListener<VideoRecommendModel> {
            override fun onSuccess(t: VideoRecommendModel) {
                if (isActivityNotActive()) return
                recommendLoadingView.hideLoading()
                if (t.data.isNullOrEmpty()) {
                    recommendGroup.visibility = View.GONE
                    return
                }
                recommendGroup.visibility = View.VISIBLE
                recommendListAdapter.setList(t.data)
            }

            override fun onFailed(msg: String) {
                if (isActivityNotActive()) return
                recommendGroup.visibility = View.VISIBLE
                recommendLoadingView.showErrorStatus(getString(R.string.error_net), getString(R.string.retry)) {
                    recommendLoadingView.showLoading()
                    recommendLoadingView.postDelayed({
                        loadVideoRecommend()
                    }, 500)
                }
            }
        })
    }


    // 显示详情页UI的关键方法
    private fun showVideoUI(videoDetail: VideoEntity) {
        // 当前的线路信息
        val currentSourceData = viewModel.getCurrentSourceData()
        if (currentSourceData == null) {
            showVideoAllSourceFailureDialog()
            return
        }
        // 设置名称
        tvVideoName.text = videoDetail.name
        // 设置收藏状态
        setFavoriteUI(videoDetail.isFavorite)
        // 设置线路相关配置
        setCurrentUserSource()
        // 设置剧集列表相关配置
        initAndDisplayEpisodeList(currentSourceData.episodes)
        // 设置总集数
        setEpisodeProgress(videoDetail.eps, currentSourceData.episodes.size)
        // 展示主体内容
        videoUIContainer.visibility = View.VISIBLE

        // 设置简介
        if (TextUtils.isEmpty(videoDetail.subtitle)) { // 无内容就是默认的简介
            tvVideoDes.text = "简介"
        } else {
            tvVideoDes.text = "简介-追剧日历"
        }

        // 关闭加载状态
        loadingView.hideLoading()

        onEpisodeClick(viewModel.currentEpisodePosition)
    }


    // 设置线路相关配置
    private fun setCurrentUserSource() {
        // 设置当前使用的线路id
        tvSourceContent.text = AppUtils.getSourceName(viewModel.currentSourceId)
    }

    // 设置剧集列表相关配置
    private fun initAndDisplayEpisodeList(episodeList: ArrayList<EpisodesResponse>) {
        // 获取当前剧集列表内容，前面已经添加了许多判断条件，此处百分百能获取到剧集数据
        episodeListAdapter.category = viewModel.videoDetailModel?.category?:Constants.VIDEO_CATEGORY_ALBUM
        episodeListAdapter.setList(episodeList)
        // 滑动剧集列表，找到当前播放的位置
        scrollToPlayingItem(viewModel.currentEpisodePosition)
    }

    // 滚动剧集列表
    private fun scrollToPlayingItem(index: Int) {
        val layoutManager = episodeRecyclerView.layoutManager as LinearLayoutManager
        if (index < layoutManager.findFirstVisibleItemPosition() || index > layoutManager.findLastVisibleItemPosition()) {
            episodeRecyclerView.post {
                episodeRecyclerView.scrollToPosition(index)
            }
        }
    }

    // 设置剧集播放进度 或 总集数
    private fun setEpisodeProgress(epi: Int, count: Int) {
        if (count <= 1) {
            tvEpisodeCount.visibility = View.GONE
        } else {
            tvEpisodeCount.visibility = View.VISIBLE
            val unit = if (viewModel.videoDetailModel?.category == Constants.VIDEO_CATEGORY_VARIFY) {
                "期"
            } else {
                "集"
            }
            tvEpisodeCount.text = if (epi > count) {
                String.format("已更新%d$unit / 共%d$unit", count, epi)
            } else {
                String.format("共%d$unit", count)
            }
        }
    }

    private fun getCurrentPlayingEpisodeIndex(): Int {
        return episodeListAdapter.data.indexOfFirst { it.isPlaying }
    }

    // 默认排序中当前正在播放视频的位置
    private fun getRealOrderEpisodeIndex(): Int {
        val playingIndex = getCurrentPlayingEpisodeIndex()
        return if (viewModel.isEpisodeReverse) {
            episodeListAdapter.data.size - playingIndex - 1
        } else {
            playingIndex
        }
    }


    // 切换剧集列表顺序
    private fun switchEpisodeListOrder() {
        if (episodeListAdapter.data.size <= 1) return
        val isEpisodeReverse = !viewModel.isEpisodeReverse
        val liat = episodeListAdapter.data.asReversed()
        val target = ArrayList(liat)
        episodeListAdapter.setList(target)
        // 滚动剧集列表
//        val index = if (isEpisodeReverse) { // 倒序，滚动到最后一个
//            episodeListAdapter.itemCount - 1
//        } else {
//            0
//        }
        scrollToPlayingItem(0)
        // 修改全屏的剧集列表顺序
        fullEpisodeView.switchEpisodeOrder()

        switchEpisodeOrderBackground(isEpisodeReverse)

        AnalysisUtils.analysis(Constants.EVENT_EPISODE_SORT, Constants.KEY_SORT_CLICK)

        val sortResult = if (isEpisodeReverse) { "倒序" } else { "正序" }
        AnalysisUtils.analysis(Constants.EVENT_EPISODE_SORT, Constants.KEY_SORT_RESULT, sortResult)
    }

    /**
     * 播放当前剧集
     * episode是默认顺序中的
     */
    private fun playEpisode(episode: EpisodesResponse, isLoadAd: Boolean = true) {
        if (TextUtils.isEmpty(episode.url)) {
            showVideoEpisodeFailureDialog()
            return
        }
        // 判断是否加载解锁广告或者插页广告
        if (episode.isLockVideoAd) { // 显示解锁广告页面
            videoPlayer.showUnlockUI()
            return
        }
        if (isLoadAd) { // 加载插页广告
            loadInterstitialAd(true)
        }

        // 停止播放视频
        videoPlayer.onVodStop()
        videoPlayer.showLoadingStatus()
        // 如果已下载的视频，无需在做解析，直接播放
        val videoName = viewModel.videoDetailModel?.name
        // 当前线路的剧集列表
        val episodeList = episodeListAdapter.data as ArrayList
        // 获取播放的真正url，有的线路需要解析
        parseVideoUrl(videoName, episode, episodeList)
    }

    private fun parseVideoUrl(videoName: String?, episode: EpisodesResponse, episodeList: ArrayList<EpisodesResponse>) {
        val sourceId = viewModel.currentSourceId
        val videoOriginUrl = episode.url
        val videoEpisodeTitle = episode.title
        AnalysisVideoTools.getVideoUrl(this, sourceId, videoOriginUrl!!, videoName, videoEpisodeTitle, object : OnParseVideoListener {
            override fun onSuccess(sourceName: String?, url: String?, headerMap: Map<String, String>?) {
                if (isActivityNotActive()) return
                if (url == null) {
                    autoChangeAvailabilitySource()
                    return
                }
                LogC.e("最终地址: " + url + "当前播放器类型：${getCurrentPlayerType()}")
                this@VideoDetailActivity.videoUrl = url

                videoPlayer.playVideo(
                    // 播放url
                    url = this@VideoDetailActivity.videoUrl!!,
                    episode.videoTitle,
                    // 跳转进度
                    startPosition =  viewModel.getPlayStartPosition(),
                    viewModel.currentEpisodePosition,
                    episodeList.size,
                    isPlayDownloadVideo = episode.isDownloaded,
                    headerMap = headerMap,
                    getCurrentPlayerType()
                )
                fullEpisodeView.onVodInit(episodeList)
            }

            override fun onFail(sourceName: String?) { // 此处反馈失败，说所有的解析以失败了
                if (isActivityNotActive()) return
                autoChangeAvailabilitySource()
            }
        })
    }


    private fun loadBannerAd() {
        if (adBannerRoot.visibility == View.VISIBLE) { // 已经加载成功，不在加载banner，banner会自动刷新
            return
        }
        bannerAdTools?.release()
        bannerAdTools = CommonAdTools()
        bannerAdTools?.loadAd(this, AdConstants.AD_ID_VIDEO_DETAIL_BANNER, object : OnLoadAdCallback() {
            override fun onAdLoaded(ad: Any?, vararg tag: Int) {
                super.onAdLoaded(ad, *tag)
                if (isActivityNotActive()) return
                adBannerRoot.visibility = View.VISIBLE
                bannerAdTools?.showAd(adBannerRoot)
            }

            override fun onAdLoadFailed(errorCode: Int) {
                super.onAdLoadFailed(errorCode)
                adBannerRoot.removeAllViews()
                adBannerRoot.visibility = View.GONE
            }

            override fun onAdComplete() {
                super.onAdComplete()
                adBannerRoot.removeAllViews()
                adBannerRoot.visibility = View.GONE
            }
        })
    }

    private fun getCurrentEpisodeIndex(): Int {
        return episodeListAdapter.data.indexOfFirst { it.isPlaying }
    }



    // 加载插页广告
    private fun loadInterstitialAd(isCheckUnlockAd: Boolean = false) {
        if (isCheckUnlockAd) {
            val episodeIndex = getCurrentEpisodeIndex()
            val episode = episodeListAdapter.getItem(episodeIndex)
            if (episode.isLockVideoAd) return
        }
        VideoInterstitialAdTools.loadAd(this, object : OnLoadAdCallback() {
            override fun onAdLoaded(ad: Any?, vararg tag: Int) {
                super.onAdLoaded(ad, *tag)
                if (isActivityNotActive()) return
                LogC.e("newShowStyle -> 显示广告...")
                videoPlayer.pause()
                videoPlayer.postDelayed({
                    if (isActivityNotActive()) return@postDelayed
                    VideoInterstitialAdTools.showAd(this@VideoDetailActivity)
                }, 500)

            }

            override fun onAdLoadFailed(errorCode: Int) {
                super.onAdLoadFailed(errorCode)
                LogC.e("newShowStyle -> 有广告缓存，并且没有广告展示, 但是出现错误...$errorCode")
                if (isActivityNotActive()) return
                // 开始播放视频
                videoPlayer.start()
            }

            override fun onAdComplete() {
                super.onAdComplete()
                if (isActivityNotActive()) return
                LogC.e("newShowStyle -> 广告展示完成...")
                // 开始播放视频
                videoPlayer.start()
            }
        })
    }

    // 点击切换剧集
    private fun onEpisodeClick(position: Int) {
        // 更新ui
        episodeListAdapter.data.forEachIndexed { index, episodesResponse ->
            episodesResponse.isPlaying = index == position
        }
        episodeListAdapter.setList(episodeListAdapter.data)
        // 尝试滚动到目标剧集
        scrollToPlayingItem(position)
        // 播放视频
        playEpisode(episodeListAdapter.getItem(position))
    }

    /**
     * 自动切换到合适的播放源
     * @return true: 无法找到合适的线路， false: 已找到合适线路
     */
    private fun autoChangeAvailabilitySource(): Boolean {
        val videoDetail = viewModel.videoDetailModel ?: return true
        if (videoDetail.sourcePlayList.isNullOrEmpty()) return true
        if (!NetworkUtils.isConnected()) { // 只有有网络的时候 自动切源
            videoPlayer.showErrorStatus("当前无网络链接，无法播放！！")
            return true
        }

        if (isManualChangeSource) {
            Log.e("自动切源 -> ", "手动切换线路，导致出现播放出错，提示用户toast")
            isManualChangeSource = false
            AlertUtils.alert("当前线路无法播放，已自动尝试切换其他线路！")
        }
        val episodeDefaultListIndex = getRealOrderEpisodeIndex()
        // 先将当前出错的视频记录下
        val currentSourceId = viewModel.currentSourceId
        var errorEpisodeList = errorSourceEpisodeMap[currentSourceId]
        if (errorEpisodeList == null) {
            errorEpisodeList = ArrayList()
            errorEpisodeList.add(episodeDefaultListIndex)
            errorSourceEpisodeMap[currentSourceId] = errorEpisodeList
        } else {
            if (!errorEpisodeList.contains(episodeDefaultListIndex)) {
                errorEpisodeList.add(episodeDefaultListIndex)
            }
        }
        Log.e("自动切源 -> ", "将出错的线路id和剧集数加入记录 -> $currentSourceId")
        // 继续找到下一个可用的源, 所有源都出错了，返回true，提示出错
        Log.e("自动切源 -> ", "遍历所有线路")
        // 默认从下一个线路开始重试
        var availabilitySource: PlayInfoResponse? = null
        // 当前的线路index
        var sourceIndex = videoDetail.sourcePlayList?.indexOfFirst { it.id == currentSourceId }?:0
        val sourceCount = videoDetail.sourcePlayList?.size?:0
        if (sourceIndex >= sourceCount - 1) {
            sourceIndex = 0
        } else {
            sourceIndex += 1
        }
        for (index in 0 until sourceCount) {
            // 寻找指定位置的线路
            if (index < sourceIndex) continue
            val playInfoResponse = videoDetail.sourcePlayList?.get(index)?:continue
            val sourceId = playInfoResponse.id
            // 跟当前的id一样的，继续查找下一个位置，一般不会出现这个条件
            if (currentSourceId == sourceId) continue
            val errorList = errorSourceEpisodeMap[sourceId]
            if (errorList.isNullOrEmpty()) { // 当前源没有出错集数，可以直接使用当前源
                Log.e("自动切源 -> ", "当前线路还没有出现过播放失败的情况，此线路可用...")
                availabilitySource = playInfoResponse
                break
            }
            // 如果当前错误剧集列表包含当前集数，说明已经使用过了，忽略
            if (errorList.contains(episodeDefaultListIndex)) continue
            // 如果当前源没有此集数，也不符合
            val episodeCount = playInfoResponse.episodes?.size ?: 0
            if (episodeDefaultListIndex > episodeCount - 1) continue
            availabilitySource = playInfoResponse
            break
        }

        if (availabilitySource == null) {
            Log.e("自动切源 -> ", "当前无可用的源")
            showVideoAllSourceFailureDialog()
            videoPlayer.showErrorStatus("当前视频无法播放！")
            return true
        }
        Log.e("自动切源 -> ", "可用的源的id -> " + availabilitySource.id)
        val playingIndex = getCurrentPlayingEpisodeIndex()
        var playingEpisode: EpisodesResponse? = null
        availabilitySource.episodes?.forEachIndexed { index, episodesResponse ->
            episodesResponse.isPlaying = index == playingIndex
            if (episodesResponse.isPlaying) {
                playingEpisode = episodesResponse
            }
        }
        // 准备播放此视频
        viewModel.currentSourceId = availabilitySource.id
        // 设置当前的线路的名称
        setCurrentUserSource()
        // 设置剧集列表相关配置
        initAndDisplayEpisodeList(availabilitySource.episodes)
        // 设置总集数
        setEpisodeProgress(videoDetail.eps, availabilitySource.episodes.size)
        if (playingEpisode == null) {
            Log.e("自动切源 -> ", "当前可用线路的剧集列表 is null -> 变为不可用的线路")
            return false
        }
        playEpisode(playingEpisode!!, false)
        return false
    }


    // 设置收藏状态
    private fun setFavoriteUI(isFavorite: Boolean) {
        ivFavorite.setBackgroundResource(
            if (isFavorite) {
                R.drawable.ic_video_favorited
            } else {
                R.drawable.ic_favorite
            }
        )
    }

    // 显示简介
    private fun showVideoDesDialog() {
        if (viewModel.videoDetailModel == null) return
        if (videoDesDialog == null) {
            videoDesDialog = VideoDesDialog(this)
        }
        viewModel.videoDetailModel?.let {
            videoDesDialog?.setDesInfo(it.name, it.director, it.actor, it.description, it.subtitle)
        }
        videoDesDialog?.show()
    }

    // 显示视频线路选择弹窗
    private fun showVideoSourceDialog() {
        val videoDetail = viewModel.videoDetailModel ?: return
        if (videoSourceDialog == null) {
            videoSourceDialog = VideoSourceDialog(this)
            videoSourceDialog?.setVideoSourceClickListener(object : VideoSourceDialog.OnVideoSourceClickListener {
                override fun onSourceClicked(source: PlayInfoResponse) {
                    val newEpisodeCount = source.episodes.size
                    if (newEpisodeCount <= 0) {
                        stopSourceReport()
                        showErrorDialog("当前视频无法正常播放，请尝试切换其他线路！", "知道了", {
                            hideErrorDialog()
                        })
                        return
                    }

                    // 每次切换线路都要恢复播放器的类型，要不然切换播放器就可能有播放器没尝试重试
                    resetPlayerTypeList()
                    // 更新当前正在观看线路id
                    viewModel.currentSourceId = source.id
                    // 设置当前的线路的名称
                    setCurrentUserSource()
                    // 设置总集数
                    setEpisodeProgress(videoDetail.eps, newEpisodeCount)

                    // 正序中单签正在播放的位置
                    val playingIndex = getCurrentPlayingEpisodeIndex()
                    source.episodes?.forEachIndexed { index, episodesResponse ->
                        episodesResponse.isPlaying = index == playingIndex
                    }

                    val realEpisodeList = if (viewModel.isEpisodeReverse) {
                        source.episodes.asReversed()
                    } else {
                        source.episodes
                    }

                    episodeListAdapter.setList(realEpisodeList)

                    // 当前正在播放的位置
                    var playIndex = getRealOrderEpisodeIndex()
                    if (playIndex >= newEpisodeCount) {
                        playIndex = newEpisodeCount - 1
                    } else if (playIndex < 0) {
                        playIndex = 0
                    }
//                    source.episodes?.forEachIndexed { index, episodesResponse ->
//                        episodesResponse.isPlaying = index == playIndex
//                    }
//                    episodeListAdapter.setList(source.episodes.asReversed())
                    // 手动选择，移除当前出错记录
                    if (errorSourceEpisodeMap.containsKey(source.id) && errorSourceEpisodeMap[source.id]?.getOrNull(playIndex) != null) {
                        errorSourceEpisodeMap[source.id]?.remove(playIndex)
                    }
                    // 设置手动点击
                    isManualChangeSource = true
                    toPlayEpisode(playIndex)
                }

                override fun onSourceResorted() {
                    // 如果让客户端排序，则需要按照剧集数多少排序
                    viewModel.sortSourceByWeight(videoDetail)
                }
            })
        }
        // 设置当前的线路纤细
        videoSourceDialog?.setVideoSource(videoDetail.id, viewModel.currentSourceId, videoDetail.sourcePlayList)
        videoSourceDialog?.show()
    }


    private fun switchEpisodeOrderBackground(currentEpisodeOrder: Boolean){
        // 无需改变排序
        if (viewModel.isEpisodeReverse == currentEpisodeOrder) return
        viewModel.isEpisodeReverse = currentEpisodeOrder
        val resId = if (viewModel.isEpisodeReverse) {
            R.drawable.ic_order_d
        } else {
            R.drawable.ic_order
        }
        tvEpisodeOrder.setBackgroundResource(resId)
    }

    // 显示剧集列表
    private fun showEpisodeDialog() {
        val videoDetail = viewModel.videoDetailModel ?: return
        if (videoEpisodeDialog == null) {
            videoEpisodeDialog = VideoEpisodeDialog(this)
            videoEpisodeDialog?.setEpisodeClickCallback(object : OnEpisodeClickCallback {
                override fun onEpisodeClick(oldPos: Int, newPos: Int, isChangeEpisode: Boolean) {
                    val currentPosition = videoPlayer.getCurrentPosition()
                    if (currentPosition > 500) { // 忽略加载未成功的剧集切换
                        updatePlayHistory()
                        // 设置已经播放标签
                        val item = episodeListAdapter.data.getOrNull(oldPos)
                        if (item != null) {
                            item.isPlayed = true
                            episodeListAdapter.notifyItemChanged(oldPos)
                        }
                    }
                    toPlayEpisode(newPos, false)
                }
            })
        }

        val result = if(viewModel.isEpisodeReverse) {
            episodeListAdapter.data.reversed()
        } else {
            episodeListAdapter.data
        }

        videoEpisodeDialog?.setEpisodes(
            videoDetail.id,
            videoDetail.category,
            result as ArrayList<EpisodesResponse>
        )
        videoEpisodeDialog?.show()
        return
    }


    // 提示当前视频已经失效
    private fun showVideoFailureDialog() {
        showErrorDialog("当前视频已失效，请返回！", "返回", {
            finish()
        })
    }


    // 提示当前线路失效
    private fun showVideoEpisodeFailureDialog() {
        showErrorDialog("当前视频已失效，请尝试使用其他线路播放此视频！", getString(R.string.confirm), {hideErrorDialog()})
    }

    // 提示当前线路失效
    private fun showVideoAllSourceFailureDialog() {
        showErrorDialog("当前视频所有线路都无法播放，请联系管理员尝试解决此问题！", getString(R.string.confirm),  {hideErrorDialog()})
    }

    override fun onNewIntent(intent: Intent?) {
        super.onNewIntent(intent)
        setIntent(intent)
        // 隐藏整体布局
        videoUIContainer.visibility = View.GONE
        // 关闭加载状态
        loadingView.showLoading()
        // 播放器stop
        videoPlayer.onVodStop()
        // 清空ViewModel的数据
        release()
        // 开始请求数据
        init(null)
    }

    private fun release() {
        isManualChangeSource = false
        // 将所有的弹窗都关闭
        videoDesDialog?.dismiss()
        videoSourceDialog?.dismiss()
        videoEpisodeDialog?.dismiss()
        videoCasScreenDialog?.dismiss()
        // 将内容滑动到顶部
        videoUIContainer.scrollTo(0, 0)
        // 将剧集列表清空
        episodeListAdapter.setList(ArrayList())
        recommendListAdapter.setList(ArrayList())
        // 清空数据
        viewModel.release()
        // 清空错误集合
        errorSourceEpisodeMap.clear()
        bannerAdTools?.release()
        adBannerRoot.removeAllViews()
        adBannerRoot.visibility = View.GONE

        pauseAdTools?.release()

        stopSourceReport()
    }

    override fun onResume() {
        super.onResume()
        videoPlayer.onVodResume()

        if (videoPlayer.isPrepared()) {
            startSourceReport()
        }
    }

    override fun onPause() {
        super.onPause()
        stopSourceReport()
        // 播放器挂起
        videoPlayer.onVodSuspend()
        // 先保存历史记录
        updatePlayHistory()
    }


    override fun onDestroy() {
        super.onDestroy()
        release()
        videoPlayer.release()
        stopSourceReport()
        VideoInterstitialAdTools.release()
    }


//    @Subscribe(threadMode = ThreadMode.MAIN)
//    fun onDownloadEvent(event: DownloadEntity) {
//        // 非本视频的下载忽略
//        if (event.videoId != videoId) return
//        // 详情页只关注删除和下载成功，2个状态
//        if (event.state != Status.SUCCESS && event.state != Status.DELETE) return
//        // 更新newPlayInfoList
//        val sourceData = viewModel.videoDetailModel?.sourcePlayList?.firstOrNull { it.id == event.sourceId }?:return
//        val episodeData = sourceData.episodes?.getOrNull(event.episode)?:return
//        episodeData.status = event.state
//        if (event.state == Status.SUCCESS) {
//            episodeData.isDownloaded = true
//            episodeData.isDownloading = true
//            sourceData.hasDownloads = true
//        } else if (event.state == Status.DELETE){
//            episodeData.isDownloaded = false
//            episodeData.isDownloading = false
//            sourceData.hasDownloads = sourceData.episodes.any { it.isDownloading }
//        }
//        if (event.sourceId == viewModel.getCurrentSourceData()?.id) {
//            episodeListAdapter.notifyItemChanged(event.episode)
//        }
//    }



    /**
     * @param position 当前剧集列表的中的位置
     */
    private fun toPlayEpisode(position: Int, isUpdateHistory: Boolean = true){
        LogC.e("切换线路 => 当前接收到的点击位置 => $position")
        stopSourceReport()

        if (isUpdateHistory) {
            // 先保存历史记录
            viewModel.currentPlayStartPosition = videoPlayer.getCurrentPosition()
            LogC.e("toPlayEpisode -> 切换线路 => 当前播放的位置 => ${viewModel.currentPlayStartPosition}")
            if (viewModel.currentPlayStartPosition > 500) { // 忽略加载未成功的剧集切换
                updatePlayHistory()

                // 设置已经播放标签
                episodeListAdapter.data.firstOrNull { it.isPlaying }?.isPlayed = true
            }
        }

        // 正序排序中的位置
        val defaultPosition = if (viewModel.isEpisodeReverse) {
            episodeListAdapter.data.size - position - 1
        } else {
            position
        }
        // 当前默认排序中当前选中的剧集
        viewModel.currentEpisodePosition = defaultPosition

        onEpisodeClick(position)
    }

    // 更新历史记录
    private fun updatePlayHistory() {
        val duration = videoPlayer.getDuration()
        val currentPosition = videoPlayer.getCurrentPosition()
        val historyPos = if (currentPosition >= duration - 5) {
            duration - 5
        } else currentPosition
        viewModel.updateVideoHistory(historyPos)
    }

    private fun loadPauseAd(){
        if (pauseAdTools == null) {
            pauseAdTools = CommonAdTools()
        }
        pauseAdTools?.loadAd(this, AdConstants.AD_ID_VIDEO_DETAIL_PAUSE, object : OnLoadAdCallback() {
            override fun onAdLoadFailed(errorCode: Int) {
                super.onAdLoadFailed(errorCode)
                videoPlayer.hidePauseAd()
            }

            override fun onAdLoaded(ad: Any?, vararg tag: Int) {
                super.onAdLoaded(ad, *tag)
                val rootView = videoPlayer.showPauseAd()?:return
                pauseAdTools?.showAd(rootView)
            }
        })
    }

    private fun getAvailablePlayer(): Int {
        if (playerList.isNotEmpty()) {
            val currentPlayerType = videoPlayer.getPlayerType()
            // 删除失效的播放器
            playerList.remove(currentPlayerType)
            // 判断是否还有可用播放器
            if (playerList.isNotEmpty()) {
                LogC.e("切换播放器 -> 尚有可用播放器使用, 当前的播放器：$currentPlayerType")
                // 切换播放
                return playerList.first()
            }
        }
        LogC.e("切换播放器 -> 已经没有可用播放器切换了")
        return -1
    }

    private fun getCurrentPlayerType(): Int {
        return if (playerList.isEmpty()) {
            -1
        }  else {
            playerList[0]
        }
    }

    private fun resetPlayerTypeList(){
        playerList.clear()
        playerList.add(PlayerType.ALIYUN)
        playerList.add(PlayerType.MEDIA3)
    }

    @Suppress("DEPRECATION")
    @Deprecated("Deprecated in Java")
    override fun onBackPressed() {
        if (isNeedToMain()) {
            val intent = Intent(this, MainActivity::class.java)
            startActivity(intent)
            finish()
        } else {
            super.onBackPressed()
        }
    }

    private var reportTimes = 0

    private val country by lazy { SPUtil.instance.czIpCountry }
    fun startSourceReport(){
        stopSourceReport()
        sourceDisposable = Flowable.interval(10, TimeUnit.SECONDS)
            .subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe {
                reportTimes++
                // 每10s记录一次播放
                val playReportStr = AppUtils.getSourceName(viewModel.currentSourceId) + "-" + country
                AnalysisUtils.analysis(Constants.EVENT_SOURCE_TIME, Constants.KEY_SOURCE_PLAY, playReportStr)
                if (reportTimes >= 6 * 5) { // 每5分钟记录一次播放成功
                    AnalysisUtils.analysis(Constants.EVENT_SOURCE_TIME, Constants.KEY_SOURCE_SUCCESS, playReportStr)
                    reportTimes = 0
                }
            }
    }

    private fun stopSourceReport(){
        reportTimes = 0
        sourceDisposable?.dispose()
    }

    // 显示投屏Dialog
    private fun showCastScreenBrowseDialog() {
        if (videoCasScreenDialog == null) {
            videoCasScreenDialog = VideoCasScreenDialog(this@VideoDetailActivity)
            videoCasScreenDialog!!.setCastScreenCallback(object : OnCastScreenCallback {
                override fun onReadyToConnect(deviceName: String) {
                    this@VideoDetailActivity.runOnUiThread {
                        videoPlayer.showCastScreenReadyToConnect(deviceName)
                    }
                }

                override fun onConnect() {
                    this@VideoDetailActivity.runOnUiThread {
                        videoPlayer.showCastScreenConnected()
                    }
                }

                override fun onDisconnect(msg: String) {
                    this@VideoDetailActivity.runOnUiThread {
                        videoPlayer.showCastScreenDisConnect(msg)
                    }
                }

                override fun onPositionUpdate(position: Long) {
                    this@VideoDetailActivity.runOnUiThread {
                        videoPlayer.updateCastScreenCurrentPosition(position)
                    }
                }

                override fun onStart() {
                    this@VideoDetailActivity.runOnUiThread {
                        videoPlayer.caseScreenSwitchPlayOrPause(true)
                    }
                }

                override fun onPause() {

                    this@VideoDetailActivity.runOnUiThread {
                        videoPlayer.caseScreenSwitchPlayOrPause(false)
                    }
                }
            })
        }
        if (TextUtils.isEmpty(videoUrl)) return
        videoCasScreenDialog?.show(videoUrl!!, viewModel.videoDetailModel?.name, videoPlayer.getCurrentPosition(), videoPlayer.getDuration().toInt())
    }



}